﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Edc.MantisClient
{
    public class Issue
    {
        public Issue(int id)
        {
            this.Id = id;
            for (int i = 0; i < _assemblyStrings.Length; i++)
            {
                _assemblyStrings[i] = new List<Assembly>();
            }
        }

        public int Id { get; internal set; }

        public string IdString
        {
            get
            {
                return string.Format("{0:0000000}", Id);
            }
        }

        public string Summary { get; set; }

        public string Description { get; set; }


        internal List<string> PendingFiles = new List<string>();
        public void AddFile(string filePath)
        {
            PendingFiles.Add(filePath);
        }

        internal Note PendingNote;
        public void AddNote(Note note)
        {
            if (PendingNote != null) throw new InvalidOperationException("Only one pending Note is allowed at a time");
            PendingNote = note;
        }


        private List<Assembly> pendingAssemblies = new List<Assembly>();
        public void AddAssembly(Assembly assembly)
        {
            pendingAssemblies.Add(assembly);
        }

        private List<Assembly>[] _assemblyStrings = new List<Assembly>[6];

        #region Assembly

        internal Assembly Assembly1
        { 
            get { return GetAssembly(1); }
            set { SetAssembly(1, value); }
        }

        internal Assembly Assembly2
        {
            get { return GetAssembly(2); }
            set { SetAssembly(2, value); }
        }

        internal Assembly Assembly3
        {
            get { return GetAssembly(3); }
            set { SetAssembly(3, value); }
        }

        internal Assembly Assembly4
        {
            get { return GetAssembly(4); }
            set { SetAssembly(4, value); }
        }

        internal Assembly Assembly5
        {
            get { return GetAssembly(5); }
            set { SetAssembly(5, value); }
        }

        internal Assembly Assembly6
        {
            get { return GetAssembly(6); }
            set { SetAssembly(6, value); }
        }

        private Assembly GetAssembly(int i)
        {
            return new Assembly()
            {
                Name = XLib20.XIterator.ToString(_assemblyStrings[i - 1], " | ", "", "", (object o) => { return ((Assembly)o).Name; }),
                Version = XLib20.XIterator.ToString(_assemblyStrings[i - 1], " | ", "", "", (object o) => { return ((Assembly)o).Version; })
            };
        }

        private void SetAssembly(int assemblyIdx, Assembly value)
        {
            var assemblyString = _assemblyStrings[assemblyIdx - 1];
            assemblyString.Clear();

            var names = value.Name.Split('|');
            var versions = value.Version.Split('|');

            // Se il campo è vuoto, Split ritorna una stringa vuota, invece di 0 elementi!
            if (string.IsNullOrEmpty(names[0])) return;
            for (int i = 0; i < names.Length; i++)
		    {
		        assemblyString.Add(new Assembly() 
                { 
                    Name = names[i].Trim(),
                    Version = i < versions.Length ? versions[i].Trim() : "" // A volte AssemblyVersion non contiene abbastanza versioni, e.g. in caso di script SQL
                });
            }
        }

        #endregion

        public void ProcessPendingItems()
        {
            foreach (var pendingAssembly in pendingAssemblies)
            {
                bool found = false;
                List<Assembly> shortestAssembly = null;
                int shortestAssemblyLength = int.MaxValue;

                foreach(var assemblies in _assemblyStrings)
    			{
                    if (assemblies.Count < shortestAssemblyLength)
                    {
                        shortestAssemblyLength = assemblies.Count;
                        shortestAssembly = assemblies;
                    }

                    var assemblyPos = assemblies.FindIndex((Assembly assembly) => { return assembly.Name.Trim() == pendingAssembly.Name; });

                    if (assemblyPos != -1)
                    {
                        // Aggiorna la versione
                        found = true;

                        // Normalizziamo il nome (se ci sono spazi in più, li trimma).
                        assemblies[assemblyPos].Name = pendingAssembly.Name;
                        assemblies[assemblyPos].Version = pendingAssembly.Version;
                        break;
                    }
                }
                
                if (!found)
                {
                    // Ok, lo aggiungiamo al più corto
                    shortestAssembly.Add(pendingAssembly);
                }
            }

            pendingAssemblies.Clear();
        }
    }
}
